/*
 * $Id$
 */
package corejs.stmt;

import corejs.rt.ActivationRecord;

import corejs.expr.Expression;


import corejs.util.XmlPrinter;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author myang
 */
public class Block extends Statement {
   
   private List<FunctionDeclaration> _fds = new ArrayList<FunctionDeclaration>();
   private List<VarDeclaration> _vds = new ArrayList<VarDeclaration>();

   private List<Statement> _stmts = new ArrayList<Statement>();

   private Block _parent;

   public Block(final Block parent) {
      _parent= parent;
   }

   @Override
   public void execute(final ActivationRecord scope) {
      final ActivationRecord currentScope = new ActivationRecord(scope);
      execute(currentScope, _fds);
      execute(currentScope, _vds);
      execute(currentScope, _stmts);
   }


   @Override
   public void accept(final StatementVisitor visitor) {
      visitor.visitBlock(_fds, _vds, _stmts);
   }

   private void print(final XmlPrinter printer,
                      final List<? extends Statement> stmts) {
      for (final Statement stmt : stmts) {
         stmt.print(printer);
      }
   }

   @Override
   public void print(final XmlPrinter printer) {
      if (!containsStatements()) {
         printer.print("block");
      }
      else {
         printer.open("block");
         print(printer, _fds);
         print(printer, _vds);
         print(printer, _stmts);
         printer.close();
      }
   }

   private void execute(final ActivationRecord scope, final List<? extends Statement> stmts) {
      for(final Statement stmt : stmts) {
         stmt.execute(scope);
      }
   }

   public Block addFunctionDeclaration(final FunctionDeclaration fd) {
      _fds.add(fd);
      return this;
   }

   public Block addVarDeclaration(final VarDeclaration vd) {
      _vds.add(vd);
      return this;
   }

   public Block addStatement(final Statement stmt) {
      _stmts.add(stmt);
      return this;
   }

   public Block addStatement(final Expression expr) {
      return addStatement(new ExpressionStatement(expr));
   }

   public boolean containsStatements() {
      return _fds.size() + _vds.size() + _stmts.size() > 0;
   }
}
